<?php
/**
 * This is User model file. 
 *
 * @copyright     Copyright 2008-2010, LilCake.net
 * @link          http://lilcake.net LilCake.net
 * @package       lil
 * @subpackage    lil.models
 * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
 */
App::uses('LilAppModel', 'Lil.Model');
/**
 * User class
 *
 * @uses          LilAppModel
 * @package       lil
 * @subpackage    lil.models
 */
class User extends LilAppModel {
/**
 * name property
 *
 * @var string 'User'
 */
	public $name = 'User';
/**
 * recursive property
 *
 * @var int
 */
	public $recursive = -1;
/**
 * validate property
 *
 * @var array
 */
	public $validate = array(
		'name'  => array(
			'rule'     => array('minLength', '1'),
			'required' => true
		),
		'repeat_pass' => array(
			'rule'       => 'testRepeatPassword',
			'required'   => false,
		),
		'old_pass' => array(
			'rule'       => 'testOldPassword',
			'required'   => false,
		),
	);
/**
 * actsAs property
 *
 * @var array
 */
	public $actsAs = array('Containable');
/**
 * __construct method
 *
 * @param mixed $id
 * @param mixed $table
 * @param mixed $ds
 * @return void
 */
	public function __construct($id = false, $table = null, $ds = null) {
		if ($displayField = Configure::read('Lil.userDisplayField')) {
			$this->displayField = $displayField;
		}
		$this->useTable = Configure::read('Lil.usersTable');
		
		if (
			(Configure::read('Lil.userDisplayField') != 'name') && 
			isset($this->validate['name']) && 
			!isset($this->validate[Configure::read('Lil.userDisplayField')])
		) {
			
			$this->validate[Configure::read('Lil.userDisplayField')] = $this->validate['name'];
			unset($this->validate['name']);
		}
		
		$this->validate[Configure::read('Lil.authFields.username')]['unique'] = array(
			'rule' => 'isUnique',
			'last' => true,
		);
		
		// associate user with areas
		if (!Configure::read('Lil.noAreas') && ($assoc = Configure::read('Lil.userAssociation'))) {
			$this->hasAndBelongsToMany['Area'] = array_merge($assoc, array('className' => 'Lil.Area'));
		}
		
		parent::__construct($id, $table, $ds);
	}
/**
 * testRepeatPassword method
 *
 * @param mixed $check
 * @return void
 */
	public function testRepeatPassword($check) {
		$value = array_values($check);
		$value = $value[0];
		if (empty($this->data['User']['passwd']) || 
			(Security::hash('', null, true) == $this->data['User']['passwd'])) {
			return true;
		}
		return isset($this->data['User']['passwd']) &&
			$this->data['User']['passwd'] == $value;
	}
/**
 * testOldPassword method
 *
 * @param mixed $check
 * @return void
 */
	public function testOldPassword($check) {
		$value = array_values($check);
		$value = $value[0];
		// return true on empty password (do nothing on empty password)
		if (empty($this->data['User']['passwd']) || 
			(Security::hash('', null, true) == $this->data['User']['passwd'])) {
			return true;
		}
		
		if (isset($this->data['User']['id'])) {
			return $this->hasAny(
				array(
					$this->primaryKey => $this->data['User'][$this->primaryKey],
					'User.passwd'     => Security::hash($value, null, true)
				)
			);
		}
		return false;
	}
/**
 * beforeSave callback
 *
 * @return boolean
 */
	public function beforeSave($options) {
		if (isset($this->data['User']['passwd'])) {
			if (
				empty($this->data['User']['passwd']) ||
				($this->data['User']['passwd'] == Security::hash('', null, true))
			) {
				unset($this->data['User']['passwd']);
			} else {
				$this->data['User']['passwd'] = Security::hash($this->data['User']['passwd'], null, true);
			}
		}
		
		return parent::beforeSave($options);
	}
/**
 * canAccessArea method
 *
 * @param mixed $user_id
 * @param mixed $area_id
 * @return boolean
 */
	public function canAccessArea($area_id = null, $user_id = null) {
		if (!empty($user_id) || ($user_id = $this->currentUser->get('id'))) {
			if ($this->role('admin', $user_id)) return true;
			
			$AreasUser =& ClassRegistry::init('Lil.AreasUser');
			
			// there is no AreasUser table so return true
			if (empty($AreasUser->useTable)) return true;
			
			$assoc = Configure::read('Lil.userAssociation');
			return $AreasUser->hasAny(array(
				$assoc['foreignKey']            => $user_id,
				$assoc['associationForeignKey'] => $area_id
			));
		} else return false;
	}
/**
 * role method
 *
 * Returns user's role or checks if user has specified role
 * If there is no role specified, current role is returned
 *
 * @param mixed $check
 * @return mixed
 */
	public function role($check = null, $user_id = null) {
		$result = $this->callPluginHandlers('user_role', array('role' => $check, 'user_id' => $user_id));
		if (is_bool($result)) return $result;
		
		if (empty($user_id) || ($user_id == $this->currentUser->get('id'))) {
			if ($check == 'admin') {
				return (bool)$this->currentUser->get(Configure::read('Lil.userAdminField'));
			}
			
			return (bool)$this->currentUser->get(Configure::read('Lil.userAdminField'));
		} else {
			return (bool)$this->field(
				Configure::read('Lil.userAdminField'),
				array('User.id' => $user_id)
			);
		}
	}
/**
 * email method
 *
 * Returns user's email
 *
 * @param mixed $user_id
 * @return mixed
 */
	public function email($user_id = null) {
		$email = $this->callPluginHandlers('user_email', $user_id);
		if (!empty($email)) return $email;
		
		if ($email_field = Configure::read('Lil.userEmailField')) {
			if (empty($user_id) || ($user_id == $this->currentUser->get('id'))) {
				return $this->currentUser->get($email_field);
			} else {
				return $this->field($email_field, array('User.id' => $user_id));
			}
		} else return false;
	}
}
